﻿using System;

namespace FFmpegLib
{
    public sealed class FrameQueue : IDisposable
    {
        private FAVFrame[] array;
        private uint capacity;
        private int size;

        public FrameQueue(int capacity = 50)
        {
            this.capacity = (uint)capacity;
            array = new FAVFrame[capacity];
        }

        public int Size() => size;

        public bool Enqueue(FAVFrame frame)
        {
            bool insertRs = false;
            lock (this)
                for (int i = 0; i < capacity; i++)
                    if (array[i] == null)
                    {
                        array[i] = frame;
                        System.Threading.Interlocked.Add(ref size, 1);
                        insertRs = true;
                        break;
                    }

            return insertRs;
        }

        /// <summary>
        /// 出队
        /// </summary>
        /// <param name="pts">ms</param>
        /// <param name="scope">单位ms</param>
        /// <returns></returns>
        public FAVFrame Dequeue(ref long pts, long scope = 40)
        {
            FAVFrame frame = null;
            lock (this)
                for (int i = 0; i < capacity; i++)
                    if (array[i] != null && Math.Abs(array[i].NewPts - pts) <= scope)
                    {
                        frame = array[i];
                        array[i] = null;
                        System.Threading.Interlocked.Add(ref size, -1);
                        break;
                    }

            return frame;
        }

        public void Clear()
        {
            lock (this)
                for (int i = 0; i < capacity; i++)
                    if (array[i] != null)
                    {
                        array[i].Dispose();
                        array[i] = null;
                    }
        }

        #region Dispose
        private bool disposedValue;

        protected void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    // TODO: 释放托管状态(托管对象)
                    Clear();
                }
                disposedValue = true;
            }
        }

        public void Dispose()
        {
            // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
            Dispose(disposing: true);
            GC.SuppressFinalize(this);
        }
        #endregion

    }
}